using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public enum EnemyStates { GUARD, PATROL, CHASE, DIE };
public enum EnemyType{ NORMAL,BOSS}
[RequireComponent(typeof(NavMeshAgent))]
[RequireComponent(typeof(CharacterStats))]
public class EnemyController : MonoBehaviour,IEndGameObserver
{
    
    private NavMeshAgent agent;
    public EnemyStates enemyStates;
    public EnemyType enemyType;
    protected GameObject attackTarget;
    private Animator anim;
    private float speed;
    private Vector3 wayPoint;
    private Vector3 guardPos;
    private float remainLookAtTime;
    protected CharacterStats characterStats;
    private float lastAttackTime;
    private Quaternion guardRoation;
    private new Collider collider;
    private bool isPlayerDied;
    

    bool isWalk;
    bool isChase;
    bool isFollow;
    bool isDeath;

    [Header("Basic setting")]
    public bool isGuard;
    public float sightRadius;
    public float lookAtTime;

    [Header("Patrol State")]
    public float patrolRange;


    public float skillTime1 = 0;
    public float skillTime2 = 0;
    private bool canSkill1;
    private bool canSkill2;
    private bool firstSkill1 = true;
    private bool firstSkill2 = true;


    private LootItem _lootItem;
    // Start is called before the first frame update
    private void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>();
        characterStats = GetComponent<CharacterStats>();
        collider = GetComponent<Collider>();
        speed = agent.speed;
        guardPos = transform.position;
        guardRoation = transform.rotation;
        _lootItem = GetComponent<LootItem>();
    }

    private void OnDisable()
    {
        if (!GameManager.IsInitialized) return;
        GameManager.Instance.RemoveObverser(this);
        if (enemyStates == EnemyStates.DIE)
        {
            if (_lootItem != null)
            {
                _lootItem.Spawnloot();
            }

            if (QuestManager.IsInitialized)
            {
                QuestManager.Instance.updateQuestProgress(this.name,1);
            }
        }
    }
    private void Start()
    {
        if (isGuard)
        {
            enemyStates = EnemyStates.GUARD;
        }
        else
        {
            enemyStates = EnemyStates.PATROL;
            GetNewWayPoint();
        }
        GameManager.Instance.AddObverser(this);
    }
    public virtual void Update()
    {
        if (characterStats.currentHealth <= 0)
            isDeath = true;
        if (!isPlayerDied)
        {
            SwitchStates();
            SwitchAnimation();
            lastAttackTime -= Time.deltaTime;
        }
        CalcuteSkillTime();
    }
    void SwitchAnimation()
    {
        anim.SetBool("Walk", isWalk);
        anim.SetBool("Chase", isChase);
        anim.SetBool("Follow", isFollow);
        anim.SetBool("Critical", characterStats.isCritical);
        anim.SetBool("Death", isDeath);
    }

    
    public void SwitchStates()
    {
        if (isDeath)
        {
            enemyStates = EnemyStates.DIE;
        }
        else if (FoundPlayer())
        {
            enemyStates = EnemyStates.CHASE;
        }
        switch (enemyStates)
        {
            case EnemyStates.GUARD:
                if (transform.position != guardPos)
                {
                    isWalk = true;
                    agent.isStopped = false;
                    agent.destination = guardPos;

                    if (Vector3.SqrMagnitude(transform.position-guardPos)<=agent.stoppingDistance)
                    {
                        isWalk = false;
                        transform.rotation = Quaternion.Lerp(transform.rotation, guardRoation, 0.01f);

                    }
                }
               
                break;
            case EnemyStates.PATROL:
                isChase = false;
                agent.speed = speed * 0.5f;
                if (Vector3.Distance(wayPoint, transform.position) <= agent.stoppingDistance)
                {
                    isWalk = false;
                    if (remainLookAtTime > 0)
                    {
                        remainLookAtTime -= Time.deltaTime;
                    }
                    else
                    GetNewWayPoint();
                }
                else
                {
                    isWalk = true;
                    agent.destination = wayPoint;
                }
                break;




            case EnemyStates.CHASE:
                if (enemyType == EnemyType.BOSS)
                {
                    sightRadius = 1000;
                }
                isWalk = false;
                isChase = true;
                //TODO:���ֵ���׷��
                if (FoundPlayer())
                {
                    isFollow = true;
                    agent.isStopped = false;
                    agent.destination = attackTarget.transform.position;
                }
                //TODO:����ս���ȥ
                else
                {
                    isFollow = false;
                    if (remainLookAtTime > 0)
                    {
                        remainLookAtTime -= Time.deltaTime;
                    }
                    else
                    {
                        if (isGuard == true)
                        {
                            enemyStates = EnemyStates.GUARD;
                        }
                        else
                        {
                            enemyStates = EnemyStates.PATROL;
                        }
                    }
                }

                if (TargetInAttackRange() || (TargetInSkill1Range()&& canSkill1) || (TargetInSkill2_1Range() && canSkill2))
                {
                    isFollow = false;
                    agent.isStopped = true;
                    if (lastAttackTime < 0)
                    {
                        lastAttackTime = characterStats.attackData.coolDown;
                        //�����ж�
                        characterStats.isCritical = Random.value < characterStats.attackData.criticalChance;


                        //��������ִ��
                        Attack();
                    }
                }
                break;
            
            case EnemyStates.DIE:
                collider.enabled = false;
                agent.radius = 0;
                //GameManager.Instance.playerStats.gameObject.GetComponent<PlayerController>().RemoveAttackTarget(this.gameObject);
                Destroy(gameObject, 2.0f);
                break;
        }

        
            
    }
    void Attack()
    {
        transform.LookAt(attackTarget.transform);

        if (enemyType == EnemyType.NORMAL)
        {
            if (TargetInAttackRange())
            {
                anim.SetTrigger("Attack");
            }
        }

        else if (enemyType == EnemyType.BOSS)
        {
            if (TargetInAttackRange() && !canSkill1 && !canSkill2)
            {
                anim.SetTrigger("Attack");
            }

            if (TargetInSkill1Range() && canSkill1)
            {
                anim.SetTrigger("Skill1");
                canSkill1 = false;
            }

            if (TargetInSkill2_1Range() && canSkill2)
            {
                anim.SetTrigger("Skill2");
                canSkill2 = false;
            }
        }
    }
    bool TargetInAttackRange()
    {
        if (attackTarget != null)
            return Vector3.Distance(transform.position, attackTarget.transform.position) <= characterStats.attackData.attackRange;
        else
            return false;
    }

    bool TargetInSkill1Range()
    {
        if (attackTarget != null)
            return Vector3.Distance(transform.position, attackTarget.transform.position) <= characterStats.attackData.skill1Range;
        else
            return false;
    }
    
    bool TargetInSkill2_1Range()
    {
        if (attackTarget != null)
            return Vector3.Distance(transform.position, attackTarget.transform.position) <= characterStats.attackData.skill2_1Range;
        else
            return false;
    }

    void GetNewWayPoint()
    {
        remainLookAtTime = lookAtTime;
        float randomX = Random.Range(-patrolRange, patrolRange);
        float randomZ = Random.Range(-patrolRange, patrolRange);
        Vector3 randomPoint = new Vector3(guardPos.x + randomX, transform.position.y, guardPos.z + randomZ);
        NavMeshHit hit;
        wayPoint = NavMesh.SamplePosition(randomPoint, out hit, patrolRange, 1) ? hit.position : transform.position;
    }

    void CalcuteSkillTime()
    {
        if (firstSkill1)
        {
            skillTime1 += Time.deltaTime;
        }

        if (firstSkill2)
        {
            skillTime2 += Time.deltaTime;
        }
        if (skillTime1 > 10)
        {
            skillTime1 = 0;
            canSkill1 = true;
            firstSkill1 = false;
        }

        if (canSkill1 == false)
        {
            skillTime1 += Time.deltaTime;
        }
        
        if (skillTime2 > 15)
        {
            skillTime2 = 0;
            canSkill2 = true;
            firstSkill2 = false;
        }

        if (canSkill2 == false)
        {
            skillTime2 += Time.deltaTime;
        }
    }

    public bool FoundPlayer()
    {
        var colliders = Physics.OverlapSphere(transform.position, sightRadius);
        foreach(var target in colliders)
        {
            if (target.CompareTag("Player"))
            {
                attackTarget = target.gameObject;
                return true;
            }
        }
        return false;
    }

    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.blue;
        Gizmos.DrawWireSphere(transform.position, patrolRange);
    }

    void Hit()
    {
        if (attackTarget!= null&&transform.IsFacingTarget(attackTarget.transform)){
            var targetStats = attackTarget.GetComponent<CharacterStats>();
        targetStats.TakeDamage(characterStats, targetStats);
        }
    }

    public void EndNotify()
    {
        //���Ż�ʤ����
        isPlayerDied = true;
        anim.SetBool("Win", true);
        isChase = false;
        isWalk = false;
        attackTarget = null;
        agent.enabled = false;
    }
}
